package buildings.dwelling;

import buildings.iterators.DwellingFloorIterator;
import buildings.exceptions.SpaceIndexOutOfBoundsException;
import buildings.Floor;
import buildings.Space;
import java.io.Serializable;
import java.util.Iterator;

public class DwellingFloor implements Floor, Serializable, Cloneable {

    private Space[] flats;

    public DwellingFloor(int flatCount) {
        if (flatCount < 0) {
            throw new SpaceIndexOutOfBoundsException();
        }
        flats = new Flat[flatCount];
        for (int i = 0; i < flatCount; i++) {
            flats[i] = new Flat();
        }
    }

    public DwellingFloor(Space[] flats) {
        if (flats.length < 1) {
            throw new SpaceIndexOutOfBoundsException();
        }
        this.flats = flats;
    }

    public int getSpaceCount() {
        return flats.length;
    }

    public float getTotalSquare() {
        float totalSquare = 0;
        for (int i = 0; i < flats.length; i++) {
            totalSquare += flats[i].getSquare();
        }
        return totalSquare;
    }

    public int getTotalRoomCount() {
        int totalCount = 0;
        for (int i = 0; i < flats.length; i++) {
            totalCount += flats[i].getRoomCount();
        }
        return totalCount;
    }

    public Space[] getSpaces() {
        return flats;
    }

    public Space getSpaceByNumber(int number) {
        Space buf = null;
        try {
            buf = flats[number];
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new SpaceIndexOutOfBoundsException();
        }
        return buf;
    }

    public void setSpaceByNumber(int number, Space flat) {
        try {
            flats[number] = flat;
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new SpaceIndexOutOfBoundsException();
        }
    }

    public void addSpaceByNumber(int number, Space flat) {
        try {
            Space[] newFlats = new Space[flats.length + 1];
            for (int i = 0; i < newFlats.length; i++) {
                if (i == number) {
                    newFlats[i] = flat;
                    continue;
                }
                if (i < number) {
                    newFlats[i] = flats[i];
                } else {
                    newFlats[i] = flats[i - 1];
                }
            }
            flats = newFlats;
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new SpaceIndexOutOfBoundsException();
        }
    }

    public void deleteSpaceByNumber(int number) {
        if (number >= 0) {
            Space[] newFlats = new Space[flats.length - 1];
            for (int i = 0; i < newFlats.length; i++) {
                if (i < number) {
                    newFlats[i] = flats[i];
                } else {
                    newFlats[i] = flats[i + 1];
                }
            }
            flats = newFlats;
        }
    }

    public Space getBestSpace() {
        int bestFlat = 0;
        float bestSquare = flats[0].getSquare();
        for (int i = 1; i < flats.length; i++) {
            if (bestSquare < flats[i].getSquare()) {
                bestSquare = flats[i].getSquare();
                bestFlat = i;
            }
        }
        return flats[bestFlat];
    }

    public Iterator iterator() {
        return new Iterator() {
            private int count = 0;
            
            public Space next() {
                if(hasNext())
                    return flats[count++];
                return null;
            }

            public boolean hasNext() {
                return flats.length < count;
            }

            public void remove() throws UnsupportedOperationException {
                throw new UnsupportedOperationException();
            }
        };
    }

    public String toString() {
        StringBuffer buf = new StringBuffer(this.getClass().getSimpleName()
                + " (" + flats.length + ",");
        for (int i = 0; i < flats.length; i++) {
            buf.append(" ");
            buf.append(flats[i]);
        }
        buf.append(")");
        return buf.toString();
    }

    public boolean equals(Object obj) {
        if(!(obj instanceof DwellingFloor))
            return false;
        boolean isSpacesEquals = true;
        for(int i = 0; i < flats.length; i++) {
            if(!((DwellingFloor)obj).getSpaceByNumber(i).equals(flats[i])) {
                isSpacesEquals = false;
                break;
            }
        }
        return((((DwellingFloor)obj).getSpaceCount() == flats.length)
                && (isSpacesEquals));
    }

    public int hashCode() {
        int hash = flats.length;
        for(int i = 0; i < flats.length; i++) {
            hash |= flats[i].hashCode();
        }
        return hash;
    }

    public Object clone() throws CloneNotSupportedException {
        Object result = super.clone();
        ((DwellingFloor)result).flats = (Space[])flats.clone();
        return result;
    }
    
    
}
